#include "views/regionview.h"
#include "ui_regionview.h"

RegionView::RegionView(QWidget *parent) :
	AbstractView(parent),
    ui(new Ui::RegionView)
{
    ui->setupUi(this);
    renderer = vtkRenderer::New();
	renderer->SetBackground(0.93,0.93,0.93);

	alwaysShowContext = false;
	
	ui->qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
}

RegionView::~RegionView()
{
    delete ui;
}

void RegionView::setInteractorStyle(View3DInteractorStyle *st)
{
	ui->qvtkWidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(st);
	st->setRenderer(renderer);

	connect(st,SIGNAL(selectedRegionsChanged(const QVector<int>&,AbstractView::SelectAction)),this, SLOT(on_selectionChanged(const QVector<int>&,AbstractView::SelectAction)));
	connect(st,SIGNAL(objectInfoRequested(const QPoint&,int,int)),this,SLOT(on_objectInfoRequested(const QPoint&,int,int)));
}

void RegionView::setNetwork(FunctionalNetwork *net)
{
	AbstractView::setNetwork(net);
	network->getTemplate()->attachToRenderer(renderer);
	renderer->ResetCamera();
}

void RegionView::on_matrixChanged()
{
	AbstractView::on_matrixChanged();
}

void RegionView::on_selectionChanged(const QVector<int> &regions, SelectAction action)
{
	SelectedLinks newSelection;

	switch(action)
	{
	case RemoveFromSelection:
		{
			if(renderMode() == FunctionalNetwork::RegionRenderer)
			{
				// in regionrendermode, the current selection contains just one region
				// so removing this is effectively the same as setting an empty selection
				setSelection(newSelection);
				//setRenderMode(LinkRenderer);
			}
			else if(renderMode() == FunctionalNetwork::LinkRenderer)
			{
				// in linkrendermode, more regions are selected
				// in this case we want to remove all links of the regions in 'regions'
				for(int i = 0;i<network->getSelection().size();i++)
				{
					AnatomicalRegion *regA = network->getSelection().at(i)->regionA();
					AnatomicalRegion *regB = network->getSelection().at(i)->regionB();
					if(!regions.contains(regA->info().RegionID) &&
						!regions.contains(regB->info().RegionID))
						newSelection.push_back(network->getSelection().at(i));
				}
			}
			setSelection(newSelection);
		};break;
	case AddToSelection:
		{
			if(renderMode() == FunctionalNetwork::RegionRenderer)
			{
				for(int j = 0;j<regions.size();j++)
				{
					AnatomicalLink* newLink = network->getLink(network->selectedRegion(),network->getRegionById(regions.at(j)));
					newSelection.push_back(newLink);
				}
			}
			else if(renderMode() == FunctionalNetwork::LinkRenderer)
			{
				for(int i = 0;i<network->getSelection().size();i++)
				{
					newSelection.push_back(network->getSelection().at(i));
					for(int j = 0;j<regions.size();j++)
					{
						AnatomicalRegion* lA = network->getSelection().at(i)->regionA();
						AnatomicalRegion* lB = network->getSelection().at(i)->regionB();
						AnatomicalLink* newLink1 = network->getLink(lA,network->getRegionById(regions.at(j)));
						AnatomicalLink* newLink2 = network->getLink(lA,network->getRegionById(regions.at(j)));
						if(!network->getSelection().contains(newLink1))
							newSelection.push_back(newLink1);
						if(!network->getSelection().contains(newLink2))
							newSelection.push_back(newLink2);
					}
				}
			}
			setSelection(newSelection);
		};break;
	case NewSelection:
		{
			if(regions.size()==1)
			{
				SelectedRegions newSelectionR;
				AnatomicalRegion *theReg = network->getRegionById(regions.at(0));
				network->setSelectedRegion(theReg);
				newSelectionR.push_back(theReg);
				setSelection(newSelectionR);
			}
		};break;
	}
}

void RegionView::updateView()
{
	if(!network)
		return;

	switch(renderMode())
	{
	case FunctionalNetwork::RegionRenderer:
		{
			//#pragma omp parallel for num_threads(4)
			for(int i = 0; i < network->getTemplate()->getNumberOfROIs(); i++)
			{
				network->getTemplate()->getRegion(i)->setVisible(true);
				network->getTemplate()->getRegion(i)->resetColor();
				network->getTemplate()->getRegion(i)->setOpacity(1);

				if(!network->getTemplate()->getRegion(i)->equals(network->selectedRegion()))
				{
					double corr = network->getLink(network->selectedRegion(),network->getTemplate()->getRegion(i))->correlation();
					double col[3];
					ColorMap::getInstance()->getLookupTable()->GetColor(corr,col);
					network->getTemplate()->getRegion(i)->setColor(col);
					double opac = abs(corr)/network->getCurrentIndividualMatrix()->maxValue();
					network->getTemplate()->getRegion(i)->setOpacity(opac);
				}
			}			
		};break;
	case FunctionalNetwork::LinkRenderer:
		{
			//#pragma omp parallel for num_threads(4)
			for(int i = 0; i < network->getTemplate()->getNumberOfROIs(); i++)
			{
				if(alwaysShowContext)
				{
					network->getTemplate()->getRegion(i)->setVisible(true);
					double gray[3] = { 0.5, 0.5, 0.5 };
					network->getTemplate()->getRegion(i)->setColor(gray);
				}
				else
				{
					network->getTemplate()->getRegion(i)->setVisible(false);
					network->getTemplate()->getRegion(i)->resetColor();
				}
				network->getTemplate()->getRegion(i)->setOpacity(1);
			}

			//#pragma omp parallel for num_threads(4)
			for(int j = 0; j < network->getSelection().size(); j++)
			{
				AnatomicalLink *link = network->getSelection().at(j);
				AnatomicalRegion *r1 = link->regionA();
				AnatomicalRegion *r2 = link->regionB();
				r1->resetColor();
				r2->resetColor();
				r1->setVisible(true);
				r2->setVisible(true);
			}
		};break;
	}	
	renderer->GetRenderWindow()->Render();
}

void RegionView::on_objectInfoRequested(const QPoint& point, int regId1, int regId2)
{
	if(regId1 == regId2)
	{
		AnatomicalRegion *reg = network->getRegionById(regId1);
		QString infoString1 = tr("Region %1 (%2)").arg(regId1).arg(reg->info().ShortName.c_str());
		QString infoString2 = tr("%1").arg(reg->info().LongName.c_str());
#ifdef _DEBUG
		QMenu menu("",this);
		menu.addAction(infoString1);
		menu.addAction(infoString2);
		menu.exec(QCursor::pos());
#else
		QToolTip::showText(QCursor::pos(),infoString1+tr("<br>")+infoString2,this);
#endif
	}
}